/**
 * 
 */
package org.statewalker.parser.xhtml.grammar;

import java.util.ArrayList;
import java.util.List;

import org.statewalker.dict.BaseDict;
import org.statewalker.validator.ValidatorGrammarConfig;

/**
 * @author kotelnikov
 */
public class TopicGrammar extends XHTMLGrammar {

    public TopicGrammar(ValidatorGrammarConfig config) {
        super(config);
    }

    private void addAfterListTransition(String key) {
        // Set<ITokenKey> keys = K.getAllParseKeys();
        // for (ITokenKey k : keys) {
        // defineTransition(key, K.UL, k, B.DOCUMENT);
        // defineTransition(key, K.OL, k, B.DOCUMENT);
        // defineTransition(key, K.DL, k, B.DOCUMENT);
        // }
    }

    @Override
    protected void addFlow(String key) {
        super.addFlow(key);
        for (String head : TopicDict.HEADS) {
            defineTransition(key, head, TopicDict.DOCUMENT);
        }
        defineSubstates(key, TopicDict.DOCUMENT);

        // defineSubstates(key, K.FORM);
        // addPCDATA(key);
        // addInline(key);
        // addMisc(key);
        //
        // // Instead of the addBlock(...) method
        // defineSubstates(key, K.DIV, K.FIELDSET);
        // addBlocktext(key);
        // defineSubstates(key, B.DOCUMENT);
    }

    @Override
    protected void addHeading(String key) {
    }

    private void addHeadsTransitions(String key) {
        for (String head : TopicDict.HEADS) {
            defineTransition(key, head, BaseDict.FINAL);
        }
    }

    private void addSectionContent(String key) {
        super.addBlockExtended(key);
    }

    /**
     * @see org.statewalker.parser.xhtml.grammar.XHTMLGrammar#getBlockContainer()
     */
    @Override
    protected String getBlockContainer() {
        return TopicDict.DEFAULT_CONTENT;
    }

    public List<String> getSectionContentContainers() {
        List<String> result = new ArrayList<String>();
        result.add(TopicDict.DEFAULT_CONTENT);
        for (String key : TopicDict.CONTENTS) {
            result.add(key);
        }
        return result;
    }

    public String getSectionDefaultContentContainers() {
        return TopicDict.DEFAULT_CONTENT;
    }

    public List<String> getSectionHeaders() {
        List<String> result = new ArrayList<String>();
        for (String key : TopicDict.HEADS) {
            result.add(key);
        }
        return result;
    }

    @Override
    public void init() {
        super.init();
        initDOCUMENT();
        initDEFAULT_SECTION();
        initSECTIONS();
    }

    @Override
    protected void initBODY() {
        init(XHTMLDict.BODY);
        defineParent(XHTMLDict.BODY, XHTMLDict.HTML);
        defineTransition(XHTMLDict.BODY, BaseDict.ANY, BaseDict.ERROR);
        defineTransition(
            XHTMLDict.BODY,
            BaseDict.ERROR,
            BaseDict.ANY,
            BaseDict.INITIAL);
        defineSubstates(XHTMLDict.BODY, TopicDict.DOCUMENT);
    }

    @Override
    protected void initDD() {
        super.initDD();
        addAfterListTransition(XHTMLDict.DD);
        addLists(XHTMLDict.DD);
    }

    protected void initDEFAULT_SECTION() {
        init(TopicDict.DEFAULT_SECTION);
        defineParent(TopicDict.DEFAULT_SECTION, TopicDict.DOCUMENT);
        defineParent(TopicDict.DEFAULT_CONTENT, TopicDict.DEFAULT_SECTION);
        defineTransition(
            TopicDict.DEFAULT_SECTION,
            BaseDict.INITIAL,
            BaseDict.ANY,
            TopicDict.DEFAULT_CONTENT);
        init(TopicDict.DEFAULT_CONTENT);
        defineSubstates(TopicDict.DEFAULT_CONTENT, TopicDict.DOCUMENT);
        // Closes the default section if there is a defined section
        for (int j = 0; j < TopicDict.SECTIONS.length; j++) {
            defineTransition(
                TopicDict.DEFAULT_CONTENT,
                TopicDict.SECTIONS[j],
                BaseDict.FINAL);
        }
        addSectionContent(TopicDict.DEFAULT_CONTENT);
    }

    @Override
    protected void initDIV() {
        super.initDIV();
        addHeadsTransitions(TopicDict.DIV);
    }

    // http://www.w3.org/TR/xhtml1/dtds.html#dtdentry_xhtml1-strict.dtd_html
    // <!ELEMENT html (head, body)>
    protected void initDOCUMENT() {
        init(TopicDict.DOCUMENT);
        defineParent(TopicDict.DOCUMENT, XHTMLDict.BODY);

        defineTransition(
            TopicDict.DOCUMENT,
            BaseDict.INITIAL,
            BaseDict.ANY,
            TopicDict.DEFAULT_SECTION);
        defineTransition(TopicDict.DOCUMENT, BaseDict.ANY, BaseDict.ERROR);

        defineTransition(
            TopicDict.DOCUMENT,
            TopicDict.DEFAULT_SECTION,
            TopicDict.DEFAULT_SECTION);
        for (int i = 0; i < TopicDict.SECTIONS.length; i++) {
            defineTransition(
                TopicDict.DOCUMENT,
                TopicDict.SECTIONS[i],
                TopicDict.SECTIONS[i]);
        }
        for (int i = 0; i < TopicDict.CONTENTS.length; i++) {
            addSectionContent(TopicDict.CONTENTS[i]);
        }
    }

    @Override
    protected void initLI() {
        super.initLI();
        addAfterListTransition(XHTMLDict.LI);
        addLists(XHTMLDict.LI);
    }

    @Override
    protected void initRoot() {
        super.initRoot();
    }

    protected void initSECTIONS() {
        for (int i = 0; i < TopicDict.SECTIONS.length; i++) {
            init(TopicDict.SECTIONS[i]);
            defineParent(TopicDict.SECTIONS[i], TopicDict.DOCUMENT);
            defineParent(TopicDict.CONTENTS[i], TopicDict.SECTIONS[i]);
            defineParent(TopicDict.HEADS[i], TopicDict.SECTIONS[i]);

            // Section
            defineTransition(
                TopicDict.SECTIONS[i],
                BaseDict.INITIAL,
                BaseDict.ANY,
                TopicDict.HEADS[i]);
            defineTransition(
                TopicDict.SECTIONS[i],
                TopicDict.HEADS[i],
                BaseDict.ANY,
                TopicDict.CONTENTS[i]);
            defineTransition(
                TopicDict.SECTIONS[i],
                TopicDict.HEADS[i],
                BaseDict.FINAL,
                TopicDict.CONTENTS[i]);

            // Content
            init(TopicDict.CONTENTS[i]);
            defineSubstates(TopicDict.CONTENTS[i], TopicDict.DOCUMENT);
            for (int j = 0; j <= i; j++) {
                defineTransition(
                    TopicDict.CONTENTS[i],
                    TopicDict.SECTIONS[j],
                    BaseDict.FINAL);
            }
            for (int j = i + 1; j < TopicDict.SECTIONS.length; j++) {
                defineTransition(
                    TopicDict.CONTENTS[i],
                    TopicDict.SECTIONS[j],
                    TopicDict.SECTIONS[j]);
            }
        }
    }

}
